package com.qqt.csr.route.service;

import com.google.common.collect.Lists;
import com.qqt.csr.common.acl.aics.resp.CsMemberInfoDTO;
import com.qqt.csr.common.utils.CacheKeyUtil;
import com.qqt.csr.route.dto.resp.CustomerServiceInfoDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;
import org.redisson.api.RScript;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 客服接待上限逻辑服务
 */
@Slf4j
@Component
public class CsReceptionLimitService {
    private static final String ALLOCATE_LIMIT_SCRIPT = "local cv = redis.call('INCRBY', KEYS[1], 0);if cv+tonumber(ARGV[2]) <= tonumber(ARGV[1]) then return redis.call('INCRBY', KEYS[1], ARGV[2]);else return 0;end;";
    private static final String RELEASE_ALLOCATED_SCRIPT = "local cv = redis.call('INCRBY', KEYS[1], 0);if cv <= tonumber(ARGV[1]) then redis.call('DEL', KEYS[1]);else redis.call('INCRBY', KEYS[1], -ARGV[1]);end;return 1;";

    @Autowired
    private RedissonClient redissonClient;
    /**
     * 释放客服进线被占用的访客名额
     *
     * @param csId
     */
    public void release(Long csId, int releaseCount) {
        if(csId == null || csId <= 0L){
            return;
        }
        String redisKey = String.format(CacheKeyUtil.CsrRoute.CS_CHAT_VISITOR_COUNT, csId);
        redissonClient.getScript().eval(
                RScript.Mode.READ_WRITE,
                RELEASE_ALLOCATED_SCRIPT,
                RScript.ReturnType.VALUE,
                Lists.newArrayList(redisKey),
                releaseCount
        );
    }

    /**
     * 释放客服进线被占用的访客名额
     *
     * @param releaseMap
     */
    public void release(Map<Long, AtomicInteger> releaseMap) {
        if (MapUtils.isEmpty(releaseMap)) {
            return;
        }
        releaseMap.forEach((csId, releaseCount) -> {
            if (releaseCount.get() <= 0) {
                return;
            }
            release(csId, releaseCount.get());
        });
    }


    /**
     * 给当前客服分配进线访客
     *
     * @param cs
     * @return
     */
    public boolean allocate(CsMemberInfoDTO cs, int allocatedCount) {
        String redisKey = String.format(CacheKeyUtil.CsrRoute.CS_CHAT_VISITOR_COUNT, cs.getUserId());
        Long result = redissonClient.getScript().eval(
                RScript.Mode.READ_WRITE,
                ALLOCATE_LIMIT_SCRIPT,
                RScript.ReturnType.VALUE,
                Lists.newArrayList(redisKey),
                cs.getReceptionLimit(), allocatedCount
        );

        return result > 0;
    }
}
